﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TypeExtensions.cs" company="Data Ductus Malmö">
//   (c) 2010 - 2012 Data Ductus Malmö AB
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DataDuctus.Snmp.Persistor.Core.MetaData.Extensions
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Reflection;

  /// <summary>
  /// The type extensions.
  /// </summary>
  public static class TypeExtensions
  {
    #region Public Methods and Operators

    /// <summary>
    /// Obtans a set of custom <see cref="Attribute"/>s from a specified <see cref="Type"/>.
    /// </summary>
    /// <typeparam name="T">
    /// The derived <see cref="Attribute"/> to obtain.
    /// </typeparam>
    /// <param name="member">
    /// The type/property/method to probe.
    /// </param>
    /// <param name="inherit">
    /// Specifies if it will probe the inheritance chain for attribute.
    /// </param>
    /// <returns>
    /// A set of zero or more of requested attributes of T.
    /// </returns>
    public static IEnumerable<T> GetAttributes<T>(this MemberInfo member, bool inherit) where T : Attribute
    {
      var attr = member.GetCustomAttributes(typeof(T), inherit) as T[];

      if (null == attr || 0 == attr.Length)
      {
        return new List<T>();
      }

      return attr;
    }

    /// <summary>
    /// The get attributes.
    /// </summary>
    /// <param name="member">
    /// The member.
    /// </param>
    /// <param name="toAdd">
    /// The to add.
    /// </param>
    /// <param name="inherit">
    /// The inherit.
    /// </param>
    /// <returns>
    /// The System.Collections.Generic.IEnumerable`1[T -&gt; System.Attribute].
    /// </returns>
    public static IEnumerable<Attribute> GetAttributes(this MemberInfo member, IEnumerable<Type> toAdd, bool inherit)
    {
      IEnumerable<Attribute> attrs = member.GetCustomAttributes(inherit).Cast<Attribute>();

      if (!attrs.Any())
      {
        return new List<Attribute>();
      }

      var attributes = new List<Attribute>();

      if (null == toAdd)
      {
        attributes.AddRange(attrs);
      }
      else
      {
        attributes.AddRange(from attr in attrs from chk in toAdd where attr.GetType() == chk select attr);
      }

      return attributes;
    }

    /// <summary>
    /// The has attribute.
    /// </summary>
    /// <param name="member">
    /// The member.
    /// </param>
    /// <param name="inherit">
    /// The inherit.
    /// </param>
    /// <typeparam name="T">
    /// </typeparam>
    /// <returns>
    /// The System.Boolean.
    /// </returns>
    public static bool HasAttribute<T>(this MemberInfo member, bool inherit)
    {
      return 0 != member.GetCustomAttributes(typeof(T), inherit).Length;
    }

    /// <summary>
    /// The has attributes.
    /// </summary>
    /// <param name="member">
    /// The member.
    /// </param>
    /// <param name="toCheck">
    /// The to check.
    /// </param>
    /// <param name="inherit">
    /// The inherit.
    /// </param>
    /// <returns>
    /// The System.Boolean.
    /// </returns>
    public static bool HasAttributes(this MemberInfo member, IEnumerable<Type> toCheck, bool inherit)
    {
      IEnumerable<Attribute> attrs = member.GetCustomAttributes(inherit).Cast<Attribute>();

      if (0 == attrs.Count())
      {
        return false;
      }

      return 0 != (from attr in attrs from chk in toCheck where attr.GetType() == chk select attr).Count();
    }

    #endregion
  }
}